import {
  assign,
  isArray,
  isBoolean,
  isNumber,
  isPlainObject,
  isString,
  keys,
  upperFirst
} from 'lodash-es';
import { isNullOrUndefined } from './is';
import { capitalize as toCapitalize } from '@vue/shared';
/**
 * @description 传入内容为空时展示处理
 * @param str 传入的内容
 * @param con 替代 str 的内容
 * @param emptyUnit 为空时的替代字符
 */
export const emptyHandle = (str: number | string | JSX.Element | undefined, con?: any,
  emptyUnit = '-') => {
  return str ? con ? con : isString(str) ? str.trim() : str : emptyUnit;
};

/**
 * @description 去除空格
 * @author wfd
 * @date 2022/1/13 15:43
 * @example
 * @param str
 * @param pos
 */
export function trimBlank (str, pos = 'both') {
  if (pos === 'both') {
    return str.replace(/^\s+|\s+$/g, '');
  } else if (pos === 'left') {
    return str.replace(/^\s*/, '');
  } else if (pos === 'right') {
    return str.replace(/(\s*$)/g, '');
  } else if (pos === 'all') {
    return str.replace(/\s+/g, '');
  } else {
    return str;
  }
}


/**
 * @description 简单添加千分位,调用 Number.prototype.toLocalString() 方法
 * @param { string | number } value
 * @param {string} replaceEmpty 代替空值的占位符 default : '-'
 * @param { 1|2|3|4 } fixed 保留小数位数
 * @returns { string }
 */
export const moneyFormatter = (value: string | number, replaceEmpty?: string,
  fixed?: 0 | 1 | 2 | 3 | 4) => {
  if (isNaN(Number(`${value}`))) {
    return replaceEmpty ?? '-';
  } else {
    return Number(value).toLocaleString('zh', {
      minimumFractionDigits: fixed ?? 2
    });
  }
};

/**
 * @description 特定的字符串传对象
 * @author wfd
 * @date 2022/2/7 21:04
 * @example
 * @param str 'color: red;background: blue'
 */
export const stringToObj = (str) => {
  const obj = {};
  str
    ? trimBlank(String(str), 'all')
    ?.split(';')
    ?.forEach((item) => {
      const str = item.split(':');
      obj[str[0]] = str[1];
    })
    : {};
  
  return obj;
};


/**
 * @description 删除对象中属性值不存的属性
 * @author wfd
 * @date 2022/9/2 13:48
 * @example
 * @param obj
 */
export function delObjValNotExist (obj) {
  for (const key in obj) {
    if (obj[key]) {
      continue;
    }
    Reflect.deleteProperty(obj, key);
  }
}


export function queryParams (data = {}, isPrefix = true, arrayFormat = 'brackets') {
  const prefix = isPrefix ? '?' : '';
  const _result: any[] = [];
  if (['indices', 'brackets', 'repeat', 'comma'].indexOf(
    arrayFormat) === -1) arrayFormat = 'brackets';
  for (const key in data) {
    const value = data[key];
    // 去掉为空的参数
    if (['', undefined, null].indexOf(value) >= 0) {
      continue;
    }
    // 如果值为数组，另行处理
    if (value.constructor === Array) {
      // e.g. {ids: [1, 2, 3]}
      switch (arrayFormat) {
      case 'indices':
        // 结果: ids[0]=1&ids[1]=2&ids[2]=3
        for (let i = 0; i < value.length; i++) {
          _result.push(key + '[' + i + ']=' + value[i]);
        }
        break;
      case 'brackets':
        // 结果: ids[]=1&ids[]=2&ids[]=3
        value.forEach((_value) => {
          _result.push(key + '[]=' + _value);
        });
        break;
      case 'repeat':
        // 结果: ids=1&ids=2&ids=3
        value.forEach((_value) => {
          _result.push(key + '=' + _value);
        });
        break;
      case 'comma':
        // 结果: ids=1,2,3
        let commaStr = '';
        value.forEach((_value) => {
          commaStr += (commaStr ? ',' : '') + _value;
        });
        _result.push(key + '=' + commaStr);
        break;
      default:
        value.forEach((_value) => {
          _result.push(key + '[]=' + _value);
        });
      }
    } else {
      _result.push(key + '=' + value);
    }
  }
  return _result.length ? prefix + _result.join('&') : '';
}

/**
 * @description 对象键合并
 * @author wfd
 * @date 2022/8/28 18:26
 * @example
 * objDeepKeyMerge({
 *   layoutHeader: {
 *     textColor: 'red'
 *   },
 *   menuHeader: {
 *     Test: '---',
 *     text: {
 *       size: 16,
 *       attrs: {
 *         love: 'love'
 *       }
 *     }
 *   },
 *   theme: 'dark'
 * })
 * {
 *   layoutHeaderTextColor: "red"
 *   menuHeaderTest: "---"
 *   menuHeaderTextAttrsLove: "love"
 *   menuHeaderTextSize: 16
 *   theme: "dark"
 * }
 * @param obj
 * @param isDeep
 */
export function objDeepKeyMerge (obj, isDeep?) {
  Object.keys(obj).forEach((item) => {
    if (isPlainObject(obj[item])) {
      Object.keys(obj[item]).forEach((subItem) => {
        obj[isDeep ? upperFirst(item) : item + upperFirst(subItem)] = obj[item][subItem];
      });
      delete obj[item];
      for (const key in obj) {
        if (isPlainObject(obj[key])) {
          objDeepKeyMerge(obj, isDeep);
        }
      }
    }
  });
  return obj;
}

/**
 * @description 根据数组的某一个 key 值区分数组
 * @author wfd
 * @date 2022/9/6 19:23
 * @example
 *   const data = [
 *     { title: '指标', isFixed: true, width: '2.4rem' },
 *     { title: '单位', isFixed: true, width: '2.4rem' },
 *     { title: '2011'  },
 *     { title: '2013'  },
 *     { title: '2013'  }
 *   ];
 *   console.log(divisionArrForKey(data, 'isFixed'));
 * @param arr
 * @param key
 * @returns {[any[], any[]]}
 */
export const divisionArrForKey = (arr, key) => {
  const trueData: any[] = [];
  const falseData: any[] = [];
  for (const item of arr) {
    if (item[key]) {
      trueData.push(item);
    } else {
      falseData.push(item);
    }
  }
  return [trueData, falseData];
};

/**
 * @description 深合并
 * @param src sourceObject
 * @param target targetObject
 * @author wfd
 * @date 2021/9/15 22:16
 * @example deepMerge({a: 1, b:2, d:6, e:{a: 3, b:4}}, {a:3, b: 4, c:5, e: {a:1, f:2}})
 */
export function deepMerge<T = any>(src: any = {}, target: any = {}): T {
  let key: string;
  for (key in target) {
    src[key] = isPlainObject(src[key]) || isArray(src[key]) ? deepMerge(src[key], target[key]) : (src[key] = target[key]);
  }
  return src;
}

export const keysOf = <T> (arr: T) => Object.keys(arr!) as Array<keyof T>;

/**
 * @description 单个属性值转对象
 * @author wfd
 * @date 2022/11/9 09:38
 * @example
 * @param params
 * @param attributeName
 * @param defaultParams
 * @returns {any}
 */
export function singleAttrToObj (
  params?: string | Record<string, any>,
  attributeName?: string,
  defaultParams?: Record<string, any>) {
  return params ? isString(
    params) ? { [attributeName!]: params, ...defaultParams } : { ...params, ...defaultParams } : { ...defaultParams };
}

/*
 * 递归辅助函数
 * @param data 待递归的数据
 * @param callback 每一个叶子项的回调
 * @param key 表示下一个节点的`key`，默认为`children`
 */
export function recursion<T extends Record<string, any>> (data: T, callback: (item: T) => void,
  key?: string): T;

export function recursion<T extends Record<string, any>> (data: T[], callback: (item: T) => void,
  key?: string): T[];

export function recursion<T extends Record<string, any>> (
  data: T | T[],
  callback: (item: T) => T,
  childrenKey = 'children'
): T[] | T {
  const _r = (data: T): T => {
    callback(data);
    return keys(data).reduce((result, key) => {
      if (key === childrenKey && isArray(data[childrenKey])) {
        return assign({ result }, { [childrenKey]: (data[childrenKey] as T[]).map((row) => _r(row)) });
      } else {
        return assign(result, { [key]: data[key] });
      }
    }, {}) as T;
  };
  
  if (isArray(data)) {
    return data.map((row) => _r(row));
  }
  return _r(data);
}

/**
 * @description 递归过滤
 * @author wfd
 * @date 2022/11/9 14:21
 * @example
 * @param {T[]} data
 * @param {(item: T) => boolean} callback
 * @param {string} childrenKey
 * @returns {T[]}
 */
export function recursionFilterTree<T> (data: T[], callback: (item: T) => boolean, childrenKey = 'children'): T[]{
  if (!isArray(data)) return [];

  return data.filter(item => {
    return callback(item);
  }).map(item => {
    item = Object.assign({}, item);
    if (isArray(item[childrenKey]) && item[childrenKey]?.length) {
      item[childrenKey] = recursionFilterTree(item[childrenKey], callback);
    }
    return item;
  }) as T[];
}

/**
 * @description 递归过滤
 * @author wfd
 * @date 2022/11/9 14:21
 * @example
 * @param {T[]} data
 * @param {(item: T) => boolean} callback
 * @param {string} childrenKey
 * @returns {T[]}
 */
export function recursionMapTree<T> (data: T[], callback: (item: T) => Record<string, any>,
  childrenKey = 'children'): T[] {
  if (!isArray(data)) return [];
  
  return data.map(item => {
    return callback(item);
  }).map(item => {
    item = Object.assign({}, item);
    if (isArray(item[childrenKey]) && item[childrenKey]?.length) {
      item[childrenKey] = recursionMapTree(item[childrenKey], callback);
    }
    return item;
  }) as T[];
}

/**
 * @description 增加单位
 * @author wfd
 * @date 2022/11/14 20:22
 * @example
 * @param {string | number} value
 * @param {boolean} unit
 * @param {number} baseSize
 * @returns {string | undefined}
 */
export function addUnit (value?: string | number, unit = false, baseSize = 50): string | undefined {
  if (!isNullOrUndefined(value)) {
    const _unit = isString(unit) ? unit : isBoolean(unit) && unit ? 'rem' : 'px';
    const isRem = _unit === 'rem';
    return isNumber(value) ? (isRem ? `${value / baseSize}rem` : `${value}${_unit}`) : String(
      value);
  }
  return undefined;
}

export const capitalize = <T extends string> (str: T) => toCapitalize(str) as Capitalize<T>;

/**
 * @description 获取某个数组最大元素在数组中的位置
 */
export const getArrMaxIndex = (arr, defaultNumber = 0) => {
  const index = arr.indexOf(Math.max(...arr));
  return index === -1 ? defaultNumber : index;
};
